package com.peng.commonlibrary.appupdate.usesystemdownload;

import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.peng.commonlibrary.Constant;
import com.peng.commonlibrary.util.SPUtils;

import java.io.File;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


/**
 * Created by M_genius on 2017/9/1 15:57.
 * 描述：下载apk的模块
 * 调用一下代码即可下载文件，并自动安装
 * DownloadAppUtils.getInstance().downloadApk(getActivity(), apkPath, "demo.apk", serverVersionName);
 */
public class DownloadAppUtils {

    private static DownloadAppUtils mInstance;

    public static DownloadAppUtils getInstance() {
        if (mInstance == null) {
            mInstance = new DownloadAppUtils();
        }
        return mInstance;
    }

    private static final String TAG = DownloadAppUtils.class.getSimpleName();

    //下载更新Apk 下载任务对应的Id
    public static long downloadUpdateApkId = -1;

    //下载更新Apk 文件路径
    public static String downloadUpdateApkFilePath;

    private static DownloadManager downloadManager;

    private ScheduledExecutorService scheduledExecutorService;

    // hander 发送处理消息的标记
    public static final int HANDLE_DOWNLOAD = 0x001;

    private BroadcastReceiver downLoadBroadcast;

    private OnProgressListener onProgressListener;
    private DownloadChangeObserver downloadObserver;

    /**
     * 下载进度监听
     * fraction 已下载/总大小
     */
    public interface OnProgressListener {
        void onProgress(float fraction, boolean isSuccess);
    }

    /**
     * 对外开发的方法
     *
     * @param onProgressListener
     */
    public void setOnProgressListener(OnProgressListener onProgressListener) {
        this.onProgressListener = onProgressListener;
    }

    /**
     * 该 Handler 为了从线程池中发送消息出来更新进度
     */
    public Handler downLoadHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (onProgressListener != null && HANDLE_DOWNLOAD == msg.what) {
                //被除数可以为0，除数必须大于0
                if (msg.arg1 >= 0 && msg.arg2 > 0) {
                    // 此处进度为百分比
                    onProgressListener.onProgress(msg.arg1 / (float) msg.arg2, false);
                }
            }
        }
    };

    /**
     * 下载最新APK
     * 权限: <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
     */
    public void downloadApk(Context context, String url, String fileName, String title) {

        String filePath = null;
        //外部存储卡存在
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            filePath = Environment.getExternalStorageDirectory().getAbsolutePath();
        } else {
            Log.i(TAG, "没有SD卡");
            return;
        }

        downloadUpdateApkFilePath = filePath + File.separator + fileName;
        // 判断文件是否存在，若存在，则删除
        deleteFile(downloadUpdateApkFilePath);

        Uri fileUri = Uri.fromFile(new File(downloadUpdateApkFilePath));

        downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
        downloadObserver = new DownloadChangeObserver();

        registerContentObserver(context);

        // 创建一个下载请求
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
        request.setTitle(title);

        /**设置用于下载时的网络状态*/
        request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);

        // VISIBILITY_VISIBLE:                   下载过程中可见, 下载完后自动消失 (默认)
        // VISIBILITY_VISIBLE_NOTIFY_COMPLETED:  下载过程中和下载完成后均可见
        // VISIBILITY_HIDDEN:                    始终不显示通知

        // 设置通知栏是否可见
        if (!UpdateAppUtils.showNotification) {
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
        }

        /**设置漫游状态下是否可以下载*/
        request.setAllowedOverRoaming(false);

        /**如果我们希望下载的文件可以被系统的 Downloads 应用扫描到并管理
         * 我们需要调用 Request 对象的 setVisibleInDownloadsUi 方法，传递参数true
         */
        request.setVisibleInDownloadsUi(true);

        //设置文件的存储地址
        request.setDestinationUri(fileUri);

        /**将下载请求放入队列， return下载任务的ID*/
        downloadUpdateApkId = downloadManager.enqueue(request);

        registerBroadcast(context);
    }

    private static boolean deleteFile(String fileStr) {
        File file = new File(fileStr);
        return file.delete();
    }

    /**
     * 注册广播
     */
    private void registerBroadcast(Context context) {

        /**注册service 广播 1.任务完成时 2.进行中的任务被点击*/
        IntentFilter intentFilter = new IntentFilter();
        // 下载完成
        intentFilter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
        // 点击通知
        intentFilter.addAction(DownloadManager.ACTION_NOTIFICATION_CLICKED);
        // 用于接收下载完成的通知
        downLoadBroadcast = new DownLoadBroadcast();

        context.registerReceiver(downLoadBroadcast, intentFilter);
    }

    /**
     * 注册 ContentObserver
     */
    private void registerContentObserver(Context context) {
        if (downloadObserver != null) {
            context.getContentResolver().registerContentObserver(Uri.parse("content://downloads/my_downloads"), false, downloadObserver);
        }
    }

    /**
     * 接受下载完成广播
     */
    private class DownLoadBroadcast extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {

            long downId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);

            switch (intent.getAction()) {
                case DownloadManager.ACTION_DOWNLOAD_COMPLETE:
                    if (downloadUpdateApkId == downId && downId != -1 && downloadManager != null) {

                        Uri downIdUri = downloadManager.getUriForDownloadedFile(downloadUpdateApkId);
                        // 关闭线程池的相关操作
                        close();

                        if (downIdUri != null) {
                            // 设置apk文件的路径，可以设置，也可以不用设置
                            SPUtils.setSharedStringData(Constant.APK_DOWNLOAD_PATH, downIdUri.getPath());

                            APPUtil.installApk(context, downIdUri);
                        }
                        if (onProgressListener != null) {
                            onProgressListener.onProgress(1.0f, true);
                        }
                    }
                    break;

                default:
                    break;
            }
        }
    }

    /**
     * 关闭定时器，线程等操作
     */
    private void close() {
        if (scheduledExecutorService != null && !scheduledExecutorService.isShutdown()) {
            scheduledExecutorService.shutdown();
        }

        if (downLoadHandler != null) {
            downLoadHandler.removeCallbacksAndMessages(null);
        }
    }

    /**
     * 监听下载进度
     */
    private class DownloadChangeObserver extends ContentObserver {

        public DownloadChangeObserver() {
            super(downLoadHandler);
            scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
        }

        /**
         * 当所监听的Uri发生改变时，就会回调此方法
         *
         * @param selfChange 此值意义不大, 一般情况下该回调值false
         */
        @Override
        public void onChange(boolean selfChange) {
            scheduledExecutorService.scheduleAtFixedRate(progressRunnable, 0, 1, TimeUnit.SECONDS);
        }
    }

    private Runnable progressRunnable = new Runnable() {
        @Override
        public void run() {
            updateProgress();
        }
    };

    /**
     * 发送Handler消息更新进度和状态
     */
    private void updateProgress() {
        int[] bytesAndStatus = getBytesAndStatus(downloadUpdateApkId);
        downLoadHandler.sendMessage(downLoadHandler.obtainMessage(HANDLE_DOWNLOAD, bytesAndStatus[0], bytesAndStatus[1], bytesAndStatus[2]));
    }

    /**
     * 通过 query 查询下载状态，包括已下载数据大小，总大小，下载状态
     *
     * @param downloadId
     * @return
     */
    private int[] getBytesAndStatus(long downloadId) {
        int[] bytesAndStatus = new int[]{-1, -1, 0};
        DownloadManager.Query query = new DownloadManager.Query().setFilterById(downloadId);
        Cursor cursor = null;
        try {
            cursor = downloadManager.query(query);
            if (cursor != null && cursor.moveToFirst()) {
                //已经下载文件大小
                bytesAndStatus[0] = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                //下载文件的总大小
                bytesAndStatus[1] = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
                //下载状态
                bytesAndStatus[2] = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));

            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return bytesAndStatus;
    }

}
